Skip to content

Add onnxscript.nn module with Module and Parameter classes#2819

Merged
justinchuby merged 25 commits intomainfrom
justinchu/nn
Feb 23, 2026
Merged

Add onnxscript.nn module with Module and Parameter classes#2819
justinchuby merged 25 commits intomainfrom
justinchu/nn

Conversation

@justinchuby
Copy link
Copy Markdown
Collaborator

@justinchuby justinchuby commented Feb 20, 2026

This pull request introduces a new PyTorch-like module interface for building ONNX graphs, enabling users to define reusable neural network components and manage parameters in a structured way. The main changes add the onnxscript.nn package, expose its API, and implement core classes for module and parameter management.

Addition of ONNX neural network module interface:

  • Added new onnxscript.nn package and exposed it in the main onnxscript API, allowing users to access neural network module functionality. (onnxscript/__init__.py, [1] [2]
  • Introduced Module and Parameter classes in onnxscript/nn/_module.py and onnxscript/nn/_parameter.py, providing a PyTorch-like interface for defining ONNX graph modules, registering parameters, and managing module hierarchies. (onnxscript/nn/_module.py, [1]; onnxscript/nn/_parameter.py, [2]
  • Created onnxscript/nn/__init__.py to expose Module and Parameter as the public API of the new package. (onnxscript/nn/__init__.py, onnxscript/nn/init.pyR1-R9)

Core module and parameter functionality:

  • Module class supports automatic registration of parameters and child modules, implements methods for iterating over parameters/modules, and provides state_dict/load_state_dict for parameter serialization/deserialization, mirroring PyTorch's API. (onnxscript/nn/_module.py, onnxscript/nn/_module.pyR1-R206)
  • Parameter class subclasses ir.Value, allowing direct use in ONNX ops and supporting initialization, realization, and representation of parameter tensors. (onnxscript/nn/_parameter.py, onnxscript/nn/_parameter.pyR1-R66)

justinchuby and others added 3 commits February 20, 2026 08:32
Introduce a PyTorch-like nn.Module interface for building ONNX graphs:

- Parameter(ir.Value): Subclasses ir.Value so parameters can be passed
  directly to ONNX ops. realize() qualifies names and registers as
  graph initializers.
- Module: Base class with automatic child module/parameter registration
  via __setattr__, hierarchical naming via push_module/pop_module,
  and forward() for subclasses to override.
- Iterators: parameters(), named_parameters(), modules(), named_modules()
- Exported via onnxscript.nn

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- children() / named_children(): iterators for immediate child modules
- state_dict(): returns dict mapping param names to tensor data
- load_state_dict(): loads tensor data into parameters, with strict mode
  for missing/unexpected keys

Also refactored Parameter to subclass ir.Value directly, eliminating
the swap/restore mechanism in Module.__call__.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add tests for:
- Module.name property
- Plain attribute assignment via __setattr__
- NotImplementedError from base Module.forward()
- Recursive parameters() with child modules

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This is an internal method called by Module.__call__, not part of
the public API.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@codecov
Copy link
Copy Markdown

codecov Bot commented Feb 20, 2026

Codecov Report

❌ Patch coverage is 93.84265% with 54 lines in your changes missing coverage. Please review.
✅ Project coverage is 71.44%. Comparing base (f69cf91) to head (eae41ac).
⚠️ Report is 1 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
onnxscript/nn/_module_test.py 92.12% 45 Missing and 1 partial ⚠️
onnxscript/nn/_parameter.py 83.33% 2 Missing and 3 partials ⚠️
onnxscript/_internal/builder.py 95.34% 1 Missing and 1 partial ⚠️
onnxscript/nn/_module.py 99.02% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2819      +/-   ##
==========================================
+ Coverage   70.76%   71.44%   +0.68%     
==========================================
  Files         231      236       +5     
  Lines       27667    28496     +829     
  Branches     2775     2819      +44     
==========================================
+ Hits        19579    20360     +781     
- Misses       7127     7171      +44     
- Partials      961      965       +4     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request introduces a PyTorch-like neural network module interface (onnxscript.nn) for building ONNX graphs in a structured, object-oriented manner. The implementation provides Module and Parameter classes that enable users to define reusable neural network components with automatic parameter registration and hierarchical naming, mirroring PyTorch's nn.Module API.

Changes:

  • Added new onnxscript.nn package with Module and Parameter classes for building ONNX graphs with a PyTorch-like interface
  • Implemented automatic parameter and submodule registration via __setattr__, hierarchical parameter naming, and state dict serialization/deserialization
  • Exposed the new package in the main onnxscript API for easy access

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
onnxscript/nn/__init__.py New package initialization exposing Module and Parameter as public API
onnxscript/nn/_parameter.py Implementation of Parameter class that subclasses ir.Value and supports realization as graph initializers
onnxscript/nn/_module.py Implementation of Module base class with automatic registration, iterators, and state dict functionality
onnxscript/nn/_module_test.py Comprehensive test suite covering parameter/module registration, forward passes, iterators, and state dict operations
onnxscript/__init__.py Updated to import and expose the new nn package in __all__

Comment thread onnxscript/nn/_parameter.py Outdated
Comment thread onnxscript/nn/_parameter.py
justinchuby and others added 2 commits February 20, 2026 09:34
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@justinchuby justinchuby changed the title Add onnxscript.nn package with Module and Parameter classes Add onnxscript.nn module with Module and Parameter classes Feb 20, 2026
Comment thread onnxscript/nn/_module.py Outdated
Comment thread onnxscript/nn/_module.py
Comment thread onnxscript/nn/_parameter.py Outdated
Append the node count to auto-generated output names (e.g.
Add_output_0 instead of Add_output) to prevent name collisions when
the same op type is called multiple times within a module. This
matches the existing node naming strategy which already uses the
count suffix.

Signed-off-by: Justin Chu <justinchuby@users.noreply.github.com>
Signed-off-by: Justin Chu <justinchuby@users.noreply.github.com>
ONNX convention uses / for node scope hierarchies. Add
_qualify_node_name() that uses / as separator, keeping qualify_name()
with . for parameter/initializer names. Node names and auto-generated
value names now use / (e.g. layer1/Add_node_0, layer1/v_Add_0) while
parameters keep . (e.g. layer1.weight).

Signed-off-by: Justin Chu <justinchuby@users.noreply.github.com>
Signed-off-by: Justin Chu <justinchuby@users.noreply.github.com>
_qualify_node_name now replaces all dots in the context prefix with /
so nested scopes produce names like layer1/attention/Add_node_0
instead of layer1.attention/Add_node_0.

Signed-off-by: Justin Chu <justinchuby@users.noreply.github.com>
- Change _context_stack from cumulative strings to a list of
  (name, class_name) tuples in _scope_stack
- push_module(name, class_name) stores individual scope entries;
  names like 'layers.3' are kept as single scopes (no dot splitting)
- qualify_name uses '.' join for parameters (layers.3.self_attn.weight)
- _qualify_value_name uses '/' join with v_ prefix (layers.3/self_attn/v_Add_0)
- _qualify_node_name uses '/' join (layers.3/self_attn/Add_node_0)
- Module.__call__ passes type(self).__qualname__ as class_name
- call_op attaches metadata_props to every node:
  - namespace: scope path + op type (e.g. 'layer1/self_attn: Add')
  - pkg.onnxscript.class_hierarchy: list of class names + op type
  - pkg.onnxscript.name_scopes: list of scope names

Signed-off-by: Justin Chu <justinchuby@users.noreply.github.com>
Signed-off-by: Justin Chu <justinchuby@users.noreply.github.com>
Value names use '.' separator with 'v_' prefix (e.g. v_layer1.attention.Add_0).
Node names and namespace strings use '/' separator (e.g. layer1/attention/Add_node_0).

Signed-off-by: Justin Chu <justinchuby@users.noreply.github.com>
Comment thread onnxscript/_internal/builder.py Fixed
Comment thread onnxscript/nn/_parameter.py Fixed
- namespace: each scope entry is 'name: class_name' joined by '/'
  e.g. 'layer1: DecoderLayer/self_attn: Attention/Add'
- scope_names() and scope_classes() return all entries (no filtering)
  so class_hierarchy and name_scopes always have matching lengths
- _scope_name_parts() filters empty names for initializer/value/node qualifying

Signed-off-by: Justin Chu <justinchuby@users.noreply.github.com>
Signed-off-by: Justin Chu <justinchuby@users.noreply.github.com>
Signed-off-by: Justin Chu <justinchuby@users.noreply.github.com>
Comment thread onnxscript/_internal/builder_test.py Fixed
Comment thread onnxscript/_internal/builder_test.py Fixed
namespace now only contains module scopes (e.g. 'layer1: DecoderLayer/self_attn: Attention').
class_hierarchy and name_scopes reflect only the module stack, not the op.

Signed-off-by: Justin Chu <justinchuby@users.noreply.github.com>
Signed-off-by: Justin Chu <justinchuby@users.noreply.github.com>
@justinchuby justinchuby requested a review from Copilot February 21, 2026 02:05
@justinchuby
Copy link
Copy Markdown
Collaborator Author

Updated how scoped names are constructed. @gramalingam

Signed-off-by: Justin Chu <justinchuby@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.

Comment thread onnxscript/nn/_parameter.py Outdated
Signed-off-by: Justin Chu <justinchuby@users.noreply.github.com>
Comment thread onnxscript/nn/_parameter.py Fixed
Comment thread onnxscript/nn/_parameter.py Outdated
Signed-off-by: Justin Chu <justinchuby@users.noreply.github.com>
Comment thread onnxscript/nn/_module_list.py Dismissed
Comment thread onnxscript/nn/_module_list.py Dismissed
Comment thread onnxscript/nn/_module_list.py Dismissed
Comment thread onnxscript/nn/_module_list.py Dismissed
Signed-off-by: Justin Chu <justinchuby@users.noreply.github.com>
Signed-off-by: Justin Chu <justinchuby@users.noreply.github.com>
Signed-off-by: Justin Chu <justinchuby@users.noreply.github.com>
Comment thread onnxscript/_internal/builder.py
Comment thread onnxscript/_internal/builder.py
Comment thread onnxscript/_internal/builder.py
@justinchuby justinchuby merged commit 8b79816 into main Feb 23, 2026
56 of 57 checks passed
@justinchuby justinchuby deleted the justinchu/nn branch February 23, 2026 23:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Development

Successfully merging this pull request may close these issues.

4 participants